/* Copyright (c)  2009  ZOHO Corp. All Rights Reserved.
 * PLEASE READ THE ASSOCIATED COPYRIGHTS FILE FOR MORE DETAILS.
 * ZOHO CORPORATION MAKES NO REPRESENTATIONS OR WARRANTIES  ABOUT THE
 * SUITABILITY OF THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING
 * BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
 * ZOHO CORPORATION SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE 
 * AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE
 * OR ITS DERIVATIVES.
 */

/**
 * @Version : 6.0.3 Mon Nov 21 22:39:09 GMT 2011
 * @Author  : WebNMS Agent Toolkit Java Edition
 */

// Any changes made to this file will be lost, if regenerated. 
// User code should be added within user tags for code merging support, if regenerated.

// Package Name (Dont Delete this comment)
package fireSystem;

// SNMP API Imports
import com.adventnet.snmp.snmp2.SnmpOID;
import com.adventnet.snmp.snmp2.SnmpVar;
import com.adventnet.snmp.snmp2.SnmpVarBind;
import com.adventnet.snmp.snmp2.agent.SnmpAgentInitializer;

// SNMP Agent API Imports
import com.adventnet.snmp.snmp2.agent.SnmpTrapService;
import com.adventnet.snmp.snmp2.agent.TrapRequestEvent;
import com.adventnet.snmp.snmp2.agent.SimpleRequestHandler;
import com.adventnet.snmp.snmp2.agent.BaseTableEntry;
import com.adventnet.snmp.snmp2.agent.BaseTableRequestHandler;
import com.adventnet.utilities.logging.LogFactory;
import com.adventnet.utils.agent.utils;

// Java Imports
import java.util.Vector;
import java.util.Hashtable;
import java.util.Enumeration;
import java.lang.reflect.Method;


/** 
 * The Class Handles the Traps generated by WebNMSSnmpAgent
 * <p>
 * This class contains includes methods to send traps/notifications.
 * <p> 
 */
public class WebNMSSnmpAgentTrap {

	WebNMSSnmpAgent agentRef = null;
	SnmpTrapService trapListener = null;

	Hashtable cacheForHandlers = new Hashtable();
	private com.adventnet.utilities.logging.Log snmpLog = null;

	/**
	 * Primary constructor for this Trap Handler
	 */
	public WebNMSSnmpAgentTrap(WebNMSSnmpAgent agentRef, SnmpTrapService trapListener){
		this.agentRef = agentRef;
		this.trapListener = trapListener;
		createLogger();
	}

	private void createLogger(){
		try{
			snmpLog = LogFactory.getInstance("SNMP");
		}catch(Exception ie){
			snmpLog.error(ie.toString(),ie.fillInStackTrace());
		}
	}

	public SimpleRequestHandler getGroup(String groupName){
		SimpleRequestHandler toRet  = (SimpleRequestHandler)cacheForHandlers.get(groupName);
		if(toRet == null){
			try{
				Class c = agentRef.getClass();
				String methodName = "get" + utils.stringFirstCharToUpper(groupName.trim());
				Method m = c.getMethod(methodName,new Class[] {});
				toRet = (SimpleRequestHandler)m.invoke(agentRef,new Object[] {});
				if(toRet != null){
					cacheForHandlers.put(groupName,toRet);
				}
			}catch(Exception exp){
				snmpLog.error("@@ Table/Scalar Group Name is wrong @@ ");
				snmpLog.error(exp.toString(),exp.fillInStackTrace());
				return null;
			}
		}
		return toRet;
	}

	public Integer getAttributeType(String groupName,String objectName){
		SimpleRequestHandler shandler = getGroup(groupName);
		if(shandler == null){
			return null;
		}
		Hashtable typeHash = shandler.getObjectTypeHash();
		if(typeHash == null){
			return null;
		}
		else{
			return (Integer)typeHash.get(objectName.toUpperCase().trim());
		}
	}

	public boolean sendNotification(String enterpriseOid, int trapIndex, Hashtable notifHash, Hashtable instanceHash, Vector extraVarbinds){
		snmpLog.trace("@@@  Inside sendNotification @@@");
		String groupName;
		String objectName;
		int inst[] = null;
		int attributeID;
		SnmpVar var;
		SnmpOID oid;
		SnmpVarBind varb;
		Object value = null;
		Vector varbinds = new Vector();
		Vector objects = new Vector();
		Hashtable values = new Hashtable();

		if(notifHash!= null && notifHash.size() > 0){
			Enumeration enumer = notifHash.keys();
			while(enumer.hasMoreElements()){
				groupName = (String) enumer.nextElement(); 
				if(instanceHash !=null){
					inst = (int[])instanceHash.get(groupName);
				}
				objects = (Vector)notifHash.get(groupName);
				// using dataCollector for collecting all the values in a particular group 
				values = dataCollector(groupName,objects,inst);
				if(values == null){
					return false;
				}
				for(int i=0; i < objects.size();i++){
					objectName=(String)objects.elementAt(i);
					Integer type= getAttributeType(groupName,objectName);
					if(type == null){
						snmpLog.trace("@@ Type is NULL.GroupName/ObjectName may be Incorrect @@");
						return false;
					}
					try{
						int temp[] = createOID(groupName,objectName, inst);
						if(temp == null){
							return false;
						}
						// Form the SnmpOid
						oid = new SnmpOID(utils.intArrayToString(temp));
						if(inst != null){
							attributeID = temp[temp.length - inst.length-1];
						}
						else{
							attributeID = temp[temp.length - 2];
						}
						value = values.get(new Integer(attributeID));
						// Form the SnmpVar
						if(value instanceof byte[]) {
							try{
								String enc = agentRef.getSnmpAPI().getCharacterEncoding();
								var = SnmpVar.createVariable(new String((byte[])value,enc),type.byteValue());
							}catch(Exception exp){
								var = SnmpVar.createVariable(new String((byte[])value),type.byteValue());
							}
						}else{
							var = SnmpVar.createVariable(value.toString(),type.byteValue());
						}
						// Forming the varbind and adding to varbinds list
						varb = new SnmpVarBind(oid,var);
						varbinds.addElement(varb);
					}catch(Exception exp){
						snmpLog.error(" @@ Problem while Sending Notification @@ ");
						snmpLog.error(exp.toString(),exp.fillInStackTrace());
						return false;
					}
				}
			}
		}
		// Adding the Extra Varbinds
		if (extraVarbinds != null){
			for (int i = 0; i < extraVarbinds.size(); i++){
				varbinds.addElement(extraVarbinds.elementAt(i));
			}
		}

		// Creating the TrapRequestEvent.
		int sourceForTrapInfo;
		if(SnmpAgentInitializer.getTargetComNotifSupport()){
			sourceForTrapInfo = TrapRequestEvent.DEFAULT;
		}
		else{
			sourceForTrapInfo = TrapRequestEvent.TFTABLE;
		}
		TrapRequestEvent te =  new TrapRequestEvent(this,
								varbinds,
								sourceForTrapInfo,
								enterpriseOid,
								trapIndex);
		te.setTimeTicks(agentRef.getUpTime());

		// Sending the Trap.
		if(trapListener != null){
			trapListener.sendTrap(te);
			try{
				agentRef.incrementSnmpOutTraps();
			}catch(Exception ase){
				snmpLog.error(ase.toString(),ase.fillInStackTrace());
				return false;
			}
		}
		return true;
	}

	public Hashtable dataCollector(String groupName,Vector objects, int[] inst){
		snmpLog.trace("@@@  Inside dataCollector @@@");
		Hashtable attributesHash = null;
		Integer attribute= null;
		Hashtable toReturn = new Hashtable();
		Vector attributesVec = new Vector();
		BaseTableEntry entry = null;
		BaseTableRequestHandler handler = null;

		try{
			SimpleRequestHandler shandler = getGroup(groupName);
			if(shandler == null){
				return null;
			}
			if(inst != null){
				// In case of Tables
				try{
					handler = (BaseTableRequestHandler)shandler;
				}catch(ClassCastException cexp){
					snmpLog.error("@@@  Instance given May be Incorrect @@@");
					snmpLog.error(cexp.toString(),cexp.fillInStackTrace());
					return null;
				}
				if(handler.tModelComplete != null){
					entry = (BaseTableEntry)handler.tModelComplete.get(inst);
				}
				else{
					entry = (BaseTableEntry)handler.getTableListener().get(inst);
				}
				if(entry == null){
					snmpLog.trace("@@@  Instance given is Incorrect @@@");
					return null;
				}
				attributesHash = handler.getObjectHash();
			}
			else{
				// In case of Scalars
				if(shandler.getInstrument() == null){
					snmpLog.trace("@@@  Instance given is Incorrect OR  instrument(of SimpleRequestHandler) is NULL @@@");
					return null;
				}
				attributesHash = shandler.getObjectHash();
			}

			Enumeration attributesEnum = new Vector().elements();

			if(objects!= null){
				if (attributesHash.size() == objects.size()){
					attributesEnum = attributesHash.elements();
				}
				else{
					for(int i=0 ;i< objects.size();i++){
						attribute = (Integer)attributesHash.get(((String)objects.elementAt(i)).toUpperCase());
						attributesVec.addElement(attribute);
					}
					attributesEnum = attributesVec.elements();
				}
			}
			else{
				return null;
			}

			if(inst!=null){
				toReturn = entry.getAttributes(attributesEnum);
			}
			else{
				toReturn = shandler.getInstrument().getAttributes(attributesEnum);
			}
			if(toReturn.size() < objects.size()) {
				snmpLog.error("@@@  Problem in dataCollector.Could'nt collect data for all the attributes @@@");
				return null;
			}
		}catch(Exception exp){
			snmpLog.error("@@@  Problem in dataCollector @@@");
			snmpLog.error(exp.toString(),exp.fillInStackTrace());
			return null;
		}
		return toReturn;
	}

	public int[] createOID(String groupName,String objectName,int[] inst){
		snmpLog.trace("@@@  Inside createOID @@@");
		Hashtable attributesHash;
		Integer attribute;
		int[] oid = null;
		try{
			SimpleRequestHandler shandler = getGroup(groupName);
			if(shandler == null){
				return null;
			}
			oid =	shandler.getOidRep();
			attributesHash =shandler.getObjectHash();
			attribute = (Integer)attributesHash.get(objectName.toUpperCase());
			if(attribute == null){
				snmpLog.trace("@@@  ObjectName may be Incorrect @@@");
				return null;
			}
			oid = utils.addIntArrays(oid,new int[]{attribute.intValue()});
			if(inst != null){
				oid = utils.addIntArrays(oid,inst);
			}
			else{
				oid = utils.addIntArrays(oid,new int[]{0});
			}
		}catch(Exception exp){
			snmpLog.error("@@@  Problem in createOID @@@");
			snmpLog.error(exp.toString(),exp.fillInStackTrace());
			return null;
		}
		return oid;
	}


	public boolean sendAlarm(Hashtable notifHash,Hashtable instanceHash,Vector extraVarbinds){

		return sendNotification(".1.3.6.1.4.1.1.2",1,notifHash,instanceHash,extraVarbinds);

	}

}
